/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/core/PGLStock.h>
#include <pgl/core/PGLDataVectors.h>
#include <pgl/core/DataRegistry.h>


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


PGL_IMPLEMENT_DYNCREATE(CPGLStock, CPGLLine);

//! Save settings
void CPGLStock::SerializeXML(CPGLArchive& ar)
{
	CString strPos;	strPos.Format(_T("%u"),(DWORD)this);
	static const TCHAR szTag[] = _T("CPGLStock");

	CString datas, str;
	std::_tstring strX,strY;

	markup::CMarkupArchive& xml = *((markup::CMarkupArchive*)ar.GetMarkup());
	if(ar.IsStoring())
	{
		ASSERT(m_pHis);
		ASSERT(m_pLows);
		ASSERT(m_pCloses);
		ASSERT(m_pOpens);
		xml.AddChildElem(szTag);
		xml.AddChildAttrib(_T("Name"),GetName());
		xml.IntoElem();
		
			// base class
			CPGLLine::SerializeXML(ar);

			xml.AddChildElem(_T("Data"));
			xml.IntoElem();
				xml.AddChildElemEx(_T("X0"), m_dX0);
				xml.AddChildElemEx(_T("Dx"), m_dDx);

				xml.AddChildElem(_T("Highs"));
				xml.IntoElem();
					m_pHis->SerializeXML(ar);
				xml.OutOfElem();
				xml.AddChildElem(_T("Lows"));
				xml.IntoElem();
					m_pLows->SerializeXML(ar);
				xml.OutOfElem();
				xml.AddChildElem(_T("Opens"));
				xml.IntoElem();
					m_pOpens->SerializeXML(ar);
				xml.OutOfElem();
				xml.AddChildElem(_T("Closes"));
				xml.IntoElem();
					m_pCloses->SerializeXML(ar);
				xml.OutOfElem();
			xml.OutOfElem();

			xml.AddChildElem(_T("DownColor"));
			xml.IntoElem();
				m_cDown.SerializeXML(ar);
			xml.OutOfElem();
		xml.OutOfElem();
	}
	else
	{
		if  (!xml.FindChildElem(szTag))
				return;

		xml.IntoElem();

			/////////////////////////////////////////////////////////
			// loading base class
			CPGLLine::SerializeXML(ar);

			xml.ResetChildPos();
			if (xml.FindChildElem(_T("Data")))
			{
				xml.IntoElem();
					xml.FindGetChildData(_T("X0"), m_dX0);
					xml.FindGetChildData(_T("Dx"), m_dDx);

					PGL_SERIALIZE_LOAD_DATA( strPos , Highs , m_pHis );
					PGL_SERIALIZE_LOAD_DATA( strPos , Lows , m_pLows );
					PGL_SERIALIZE_LOAD_DATA( strPos , Opens , m_pOpens );
					PGL_SERIALIZE_LOAD_DATA( strPos , Closes , m_pCloses );

				xml.OutOfElem();
			}

			xml.ResetChildPos();
			if (xml.FindChildElem(_T("DownColor")))
			{
				xml.IntoElem();
					m_cDown.SerializeXML(ar);
				xml.OutOfElem();
			}
		xml.OutOfElem();

		PostUpdateExtent();
	}
}

#ifdef _DEBUG
void CPGLStock::Dump( CDumpContext& dc ) const
{
    // call base class function first
    CPGLLine::Dump( dc );

    // now do the stuff for our specific class
	dc << _T("CPGLStock ID ") << GetID() << "\n";
}
void CPGLStock::AssertValid() const
{
    // call inherited AssertValid first
    CPGLLine::AssertValid();
} 
#endif


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLStock::CPGLStock(const CPGLColor& _FrontColor, const CPGLColor& _FillColor)
: CPGLLine(_FrontColor, _FillColor), m_dX0(0), m_dDx(0), m_dwType(TypeCandleStick), m_cDown(0.8f, 0, 0)
{
}

CPGLStock::~CPGLStock()
{
	ClearData();
}

CPGLStock& CPGLStock::operator = (const CPGLStock& st)
{
	if(this != &st)
	{
		this->CPGLLine::operator =(st);

		m_dX0 = st.m_dX0;
		m_dDx = st.m_dDx;

		ClearData();

		m_pHis = st.m_pHis->Clone();
		m_pCloses = st.m_pCloses->Clone();
		m_pLows = st.m_pLows->Clone();
		m_pOpens = st.m_pOpens->Clone();

		m_cDown = st.m_cDown;

		m_dwType = st.m_dwType;

		m_rLimitIndices = st.m_rLimitIndices;
	}
	return *this;
}

void CPGLStock::SetDatas(CPGLDataPtr pHis, CPGLDataPtr pLows, CPGLDataPtr pOpens, CPGLDataPtr pCloses)
{
	m_pHis = pHis;
	m_pLows = pLows;
	m_pCloses = pCloses;
	m_pOpens = pOpens;

	PostUpdateExtent();
}

void CPGLStock::SetDatas(const std::vector<float>& _vHis, const std::vector<float>& _vLows, const std::vector<float>& _vOpens, const std::vector<float>& _vCloses, bool bMakeOwnCopy)
{
	if (bMakeOwnCopy)
	{
		SetDatas(
			CPGLVectorFPtr(new CPGLVectorF(_vHis)), 
			CPGLVectorFPtr(new CPGLVectorF(_vLows)), 
			CPGLVectorFPtr(new CPGLVectorF(_vOpens)), 
			CPGLVectorFPtr(new CPGLVectorF(_vCloses)) );
	}
	else
	{
		SetDatas(
			CPGLVectorRefFPtr(new CPGLVectorRefF(_vHis)), 
			CPGLVectorRefFPtr(new CPGLVectorRefF(_vLows)), 
			CPGLVectorRefFPtr(new CPGLVectorRefF(_vOpens)), 
			CPGLVectorRefFPtr(new CPGLVectorRefF(_vCloses)) );
	}
}

void CPGLStock::PlotLineStripGfx(gfxinterface::CGfxInterface& gfx)
{
	using namespace gfxinterface;

	DWORD stockType = GetEStockType();

	gfx.DrawStock( m_dX0, m_dDx, *m_pHis, *m_pLows, *m_pOpens, *m_pCloses, m_cDown.GetRGBA(), stockType);
}

DWORD CPGLStock::GetEStockType()
{
	DWORD dwType=0;
	if (m_dwType & TypeCandleStick)
		dwType |= gfxinterface::StockTypeCandleStick;

	else if (m_dwType & TypeOpenHighLowClose)
		dwType |= gfxinterface::StockTypeOpenHighLowClose;

	return dwType;
}


	//! Extent computation
void CPGLStock::GetUnionExtent(gfxinterface::CGfxInterface& gfx, CPGLRectD& rExtent)
{
	CPGLLine::GetUnionExtent(gfx,rExtent);

	GetExtent().SetUnion(rExtent);

	rExtent.xValid = true;
	rExtent.yValid = true;
}
    ///virtual function to override in derived classes
void CPGLStock::UpdateExtent(gfxinterface::CGfxInterface& gfx)
{
	CPGLLine::UpdateExtent(gfx);

	m_rLimitIndices=CPGLRectU();

	UINT nPoints=GetNPoints();
	if (nPoints == 0)
	{
		SetExtent( CPGLRectD::GetNormBox() );
		return;
	}

	// updating...
	CPGLRectD rExtent;

	rExtent.left=m_dX0;
	rExtent.right=m_dX0+(nPoints-1)*m_dDx;	

	rExtent.bottom=(*m_pLows)[m_pLows->GetMinIndex()];	
	rExtent.top=(*m_pHis)[m_pHis->GetMaxIndex()];	

	// setting extent
	SetExtent(rExtent);
}

void CPGLStock::ClearData()
{
	m_pHis.reset();
	m_pLows.reset();
	m_pOpens.reset();
	m_pCloses.reset();
}
